$webwork.htmlEncode($page.space.name) : GetFeatureInfo templates
This page last changed on Oct 19, 2007 by groldan.
This tutorial describes how to use the GeoServer template system to create custom HTML GetFeatureInfo responses. IntroductionGetFeatureInfo is a WMS standard call allowing to retrieve informations about features and coverages displayed in a map. The map can be composed of various layers, and GetFeatureInfo can be instructed to return multiple feature descriptions, which may be of different types. GetFeatureInfo can generate output in various formats, at the time of writing, GML2, plain text and HTML. Templating is concerned with the HTML one. The default HTML output is a sequence of titled tables, each one for a different layer. The following example shows the default output for the tiger-ny basemap (included in the above cited releases, and onwards): Standard templatesThe following assumes you're already up to speed with Freemarker templates. If you're not, read the Freemarker templates tutorial, and the KML Placemark templates page, which has simple examples. The default output is generated by the standard templates, which are three:
The header template is invoked just once, and usually contains the start of the HTML page, along with some CSS. The default header template looks like this (as you can see, it's completely static, and it's in fact not provided with any variable you could expand): <#-- Header section of the GetFeatureInfo HTML output. Should have the <head> section, and a starter of the <body>. It is advised that eventual css uses a special class for featureInfo, since the generated HTML may blend with another page changing its aspect when usign generic classes like td, tr, and so on. --> <html> <head> <title>Geoserver GetFeatureInfo output</title> </head> <style type="text/css"> table.featureInfo, table.featureInfo td, table.featureInfo th { border:1px solid #ddd; border-collapse:collapse; margin:0; padding:0; font-size: 90%; padding:.2em .1em; } table.featureInfo th{ padding:.2em .2em; text-transform:uppercase; font-weight:bold; background:#eee; } table.featureInfo td{ background:#fff; } table.featureInfo tr.odd td{ background:#eee; } table.featureInfo caption{ text-align:left; font-size:100%; font-weight:bold; text-transform:uppercase; padding:.2em .2em; } </style> <body> The footer template is similar, a static template used to close the HTML document properly: <#-- Footer section of the GetFeatureInfo HTML output. Should close the body and the html tag. --> </body> </html> The content template is the one turning feature objects into actual HTML tables. The template is called multiple times, each time it's fed with a different feature collection, whose features all have the same type. In the above example, the template have been called once for the roads, and once for the points of interest (POI). <#-- Body section of the GetFeatureInfo template, it's provided with one feature collection, and will be called multiple times if there are various feature collections --> <table class="featureInfo"> <caption class="featureInfo">${type.name}</caption> <tr> <#list type.attributes as attribute> <#if !attribute.isGeometry> <th >${attribute.name}</th> </#if> </#list> </tr> <#assign odd = false> <#list features as feature> <#if odd> <tr class="odd"> <#else> <tr> </#if> <#assign odd = !odd> <#list feature.attributes as attribute> <#if !attribute.isGeometry> <td>${attribute.value}</td> </#if> </#list> </tr> </#list> </table> <br/> As you can see there is a first loop scanning type and outputting its attributes into the table header, then a second loop going over each feature into the collection (features). Custom templatesSo, what you have to do if you want to override the custom templates? Well, it depends on which template you want to override. For example, let's say you would like better a bulleted list appearance for your feature info output, and you want this to be applied to all GetFeatureInfo HTML output. In that case you would drop the following content.ftl in the featureTypes directory: <ul> <#list features as feature> <li><b>Type: ${type.name}</b> (id: <em>${feature.fid}</em>): <ul> <#list feature.attributes as attribute> <#if !attribute.isGeometry> <li>${attribute.name}: ${attribute.value}</li> </#if> </#list> </ul> </li> </#list> </ul> With this template in place, the output would be: Looking at the output we notice point of interest features refer to image files, that we know are stored inside the default GeoServer distribution in the demo_app/pics path. So, we could provide a POI specific override that actually loads the images. <ul> <#list features as feature> <li><b>Point of interest, "${feature.NAME.value}"</b>: <br/> <img src="http://localhost:8080/geoserver/popup_map/${feature.THUMBNAIL.value}"/> </li> </#list> </ul> With this additional template, the output is: As you can see, roads are still using the generic template, whilst POI is using its own custom template. Advanced formatingThe value property of Feature attribute values are given by geoserver in String form, using a sensible default depending on the actual type of the attribute value. |
![]() |
Document generated by Confluence on Jan 16, 2008 23:27 |